﻿using System;

namespace StackExchange.Redis.Extensions.Lock
{
    public static class IDatabaseExtension
    {
        public static TResult DistributionLock<TResult>(this IDatabase redisDb, string key, int expireSeconds, Func<string, TResult> func)
        {
            TResult result = default(TResult);

            var LockId = Guid.NewGuid().ToString();

            var isLocked = LockString(redisDb, key, LockId, expireSeconds);

            if(isLocked)
            {
                using (var heartbeat = new LockHeartbeat(redisDb, key, expireSeconds))
                {
                    try
                    {
                        result = func(key);
                    }
                    catch
                    {
                        //TODO
                    }
                }

                if (LockId == redisDb.StringGet(key))
                {
                    redisDb.KeyDelete(key);
                }
                    
            }

            return result;
        }

        private static bool LockString(IDatabase redisDb, string key, string value, int expireSeconds)
        {
            var expireTime = TimeSpan.FromSeconds(expireSeconds);
            var result = redisDb.StringSet(key, value, expireTime, When.NotExists);
            return result;
        }
    }
}
